package be.ipl.finito.usecasesimpl;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import be.ipl.finito.dao.CaseDao;
import be.ipl.finito.dao.JoueurDao;
import be.ipl.finito.dao.PartieDao;
import be.ipl.finito.dao.PlateauDao;
import be.ipl.finito.domaine.Case;
import be.ipl.finito.domaine.Jeton;
import be.ipl.finito.domaine.Joueur;
import be.ipl.finito.domaine.Partie;
import be.ipl.finito.domaine.Partie.Etat;
import be.ipl.finito.domaine.Plateau;
import be.ipl.finito.exceptions.ArgumentInvalideException;
import be.ipl.finito.exceptions.JoueurDejaInscritException;
import be.ipl.finito.exceptions.JoueurInExistantException;
import be.ipl.finito.exceptions.PartieException;
import be.ipl.finito.exceptions.PartieInExistanteException;
import be.ipl.finito.exceptions.PlateauInExistantException;
import be.ipl.finito.exceptions.TourInexistantException;
import be.ipl.finito.usecases.GestionPartie;
import be.ipl.finito.util.Util;

@Stateless
public class GestionPartieImpl implements GestionPartie{

	@EJB private PartieDao partieDao;
	
	@EJB private JoueurDao joueurDao;
	
	@EJB private PlateauDao plateauDao;
	
	@EJB private CaseDao caseDao;
	
	@Override
	public Partie creerPartie(String nomPartie) throws IllegalArgumentException, PartieException{
		Util.checkString(nomPartie);
		Partie partie = this.partieDao.chercherPartie(nomPartie);
		if(partie != null) {
			throw new PartieException("Ce nom de partie est déjà utilisé !");
		}
		return this.partieDao.creerPartie(nomPartie);
	}

	@Override
	public Partie rejoindrePartie(int id, Joueur joueur)
			throws ArgumentInvalideException, PartieInExistanteException, JoueurInExistantException, JoueurDejaInscritException {
		
		Partie partie = this.partieDao.chercherPartie(id);
		if(partie == null)
			throw new PartieInExistanteException();
		joueur = this.joueurDao.rechercher(joueur.getId());
		if(joueur == null)
			throw new JoueurInExistantException();
		
		if (partie.getJoueurs().size() >= Partie.NBR_MAX_JOUEURS)
			return null;
		
		Plateau plateau = new Plateau(joueur, partie);
		if(partie.getPlateaux().contains(plateau)){
			throw new JoueurDejaInscritException();
		}
		
		plateau = this.plateauDao.creerPlateau(joueur, partie);
		plateau = this.plateauDao.chargerCase(plateau);
		
		partie.ajouterPlateau(plateau);
		
		
		partie = this.partieDao.mettreAJour(partie);
		return this.partieDao.chargerPlateaux(partie);
	}

	/*
	 * JAMAIS SUPPRIMER DE LA DB !!!!! 
	@Override
	public void supprimerPartie(int id)
			throws ArgumentInvalideException, PartieInExistanteException {
		Partie p = partieDao.chercherPartie(id);
		if(p == null){
			throw new PartieInExistanteException();
		}
		partieDao.supprimer(id);
	}*/

	@Override
	public List<Partie> listerPartiesEnAttente() {
		return this.partieDao.listerPartiesEnAttente();
	}

	@Override
	public List<Partie> listerParties() {
		List<Partie> tmp = partieDao.lister();
		List<Partie> listeParties = new ArrayList<Partie>();
		for (Partie partie : tmp) {
			if(partie.getEtat() == Etat.EN_ATTENTE){
				Partie p = partieDao.chargerPlateaux(partie);
				listeParties.add(p);
			}
		}
		return listeParties;
	}


	@Override
	public Partie chercherPartie(int idPartie) throws PartieInExistanteException{
		Partie partie = this.partieDao.rechercher(idPartie);
		if (partie == null)
			throw new PartieInExistanteException();
		partie = partieDao.chargerPlateaux(partie);
		return partie;
	}

	

	@Override
	public Partie deplacerJeton(String login, String nomPartie, int position)
			throws ArgumentInvalideException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int nbrJoueurs(int idPartie) {
		Partie partie = this.partieDao.rechercher(idPartie);
		return partie.getJoueurs().size();
	}

	@Override
	public boolean annulerPartie(int idPartie, Joueur joueur) throws PartieInExistanteException, JoueurInExistantException {
		Util.checkObject(joueur);
		Partie partie = this.partieDao.rechercher(idPartie);
		if (partie == null)
			throw new PartieInExistanteException();
		joueur = this.joueurDao.rechercher(joueur.getId());
		if (joueur == null)
			throw new JoueurInExistantException();

		Partie pl = this.partieDao.chargerPlateaux(partie);
		
		for (Plateau plateau : pl.getPlateaux()) {
			if(plateau.getJoueur().equals(joueur))
				this.plateauDao.supprimer(pl.getId());
		}
		
		boolean partieAnnulee = partie.supprimerPartie();
		if (!partieAnnulee)
			return false;
		this.partieDao.mettreAJour(partie);
		return true;
	}

	@Override
	public synchronized Partie commencerPartie(int idPartie, Joueur joueur) throws PartieInExistanteException, JoueurInExistantException {
		Util.checkObject(joueur);
		Partie partie = this.partieDao.rechercher(idPartie);
		if (partie == null)
			throw new PartieInExistanteException();
		joueur = this.joueurDao.rechercher(joueur.getId());
		if (joueur == null)
			throw new JoueurInExistantException();
		

		partie = this.partieDao.chargerPlateaux(partie);
		

		boolean partieEngagee = partie.demarrerPartie();
		partie = this.partieDao.mettreAJour(partie);
		
		if (partieEngagee)
			return partie;
		
		return null;
	}

	@Override
	public boolean estCommencee(int idPartie) throws PartieInExistanteException {
		Partie p = chercherPartie(idPartie);
		if(p == null){
			throw new PartieInExistanteException();
		}
		return p.getEtat() == Etat.EN_COURS;
	}

	@Override
	public boolean estAnnulee(int idPartie) throws PartieInExistanteException {
		Partie p = chercherPartie(idPartie);
		if(p == null){
			throw new PartieInExistanteException();
		}
		return p.getEtat() == Etat.SUPPRIMER;
	}
	
	
	
	
	@Override
	 public boolean placerJeton(Joueur joueur, Partie partie, int position) throws JoueurInExistantException, PartieInExistanteException, PlateauInExistantException {
	  Util.checkObject(partie);
	  Util.checkObject(joueur);
	  Util.checkObject(joueur);
		Util.checkObject(partie);
		joueur = this.joueurDao.rechercher(joueur.getId());
		if (joueur == null)
			throw new JoueurInExistantException();
		partie = this.partieDao.rechercher(partie.getId());
		if (partie == null)
			throw new PartieInExistanteException();
		Plateau pl = this.plateauDao.recupererPlateau(joueur, partie);
		if (pl == null)
			throw new PlateauInExistantException();
		// Si la partie n'est pas en cours, on sort
		if (partie.getEtat() != Partie.Etat.EN_COURS){
			System.out.println("La partie n'est pas en cours!");
			return false;
		}

		
		if (position < 1 || position >= 36) {
			return false;
		}
		Jeton jetonCr = partie.prochainJeton();
		Case c = new Case(position);
		c.setJeton(jetonCr);
		if (!pl.ajouterJeton(c) ) 
			return false;
		pl = this.plateauDao.mettreAJour(pl);
		partie = this.partieDao.chargerPlateaux(partie);
		partie = this.partieDao.mettreAJour(partie);
		if (partie.toutLeMondeAJoue()) {
			//TODO
			partie = this.partieDao.mettreAJour(partie);
		}
		return true;
	  
	 }
	
	@Override
	public Partie chargeTour(int idPartie) throws PartieInExistanteException{
		Partie p = this.partieDao.recharger(idPartie);
		if (p == null)
			throw new PartieInExistanteException();
		p.getPioches().size();
		return p;
	}
	
	public Jeton getJetonDuTour(int idPartie, int tour) throws TourInexistantException, PartieInExistanteException{
		Partie partie = this.partieDao.rechercher(idPartie);
		if (partie == null)
			throw new PartieInExistanteException();
		partie = this.partieDao.chargerJetons(partie);

		Jeton res = partie.getPioches().get(tour);
		if (res == null)
			throw new TourInexistantException();
		return res;
	}

}
